import os
from typing import TextIO

from bean.Constants import Constants
from bean.TableInfo import TableInfo

from builder.CommentBuilder import CommentBuilder
from utils.StringUtils import lower_first_char, uppercase_first_char


class ControllerBuilder:
    @staticmethod
    def execute_build(table_info: TableInfo) -> None:
        if not os.path.exists(Constants.get_instance().CONTROLLER_PATH):
            os.makedirs(Constants.get_instance().CONTROLLER_PATH)

        with open(Constants.get_instance().CONTROLLER_PATH + f"{table_info.bean_name}Controller.java", "w",
                  encoding="utf-8") as f:
            f.write(f"package {Constants.get_instance().PACKAGE_CONTROLLER};")
            f.write("\n\n")
            ControllerBuilder.build_class_and_imports(f, table_info)
            f.write("\n")
            ControllerBuilder.build_impls(f, table_info)
            f.write("}")

    @staticmethod
    def build_class_and_imports(file_pointer: TextIO, table_info: TableInfo) -> None:
        def build_controller_comment():
            if table_info.comment != "":
                CommentBuilder.build_class_comment(file_pointer, table_info.comment + " 控制层")
            else:
                CommentBuilder.build_class_comment(file_pointer, table_info.comment)

        file_pointer.write(f"import {Constants.get_instance().PACKAGE_PO}.{table_info.bean_name};")
        file_pointer.write("\n")
        file_pointer.write(f"import {Constants.get_instance().PACKAGE_PARAM}.{table_info.bean_param_name};")
        file_pointer.write("\n")
        file_pointer.write(f"import {Constants.get_instance().PACKAGE_SERVICE}.{table_info.bean_name}Service;")
        file_pointer.write("\n")
        file_pointer.write(f"import {Constants.get_instance().PACKAGE_VO}.ResponseVO;")
        file_pointer.write("\n")
        file_pointer.write("import jakarta.annotation.Resource;")
        file_pointer.write("\n")
        file_pointer.write("import org.springframework.web.bind.annotation.RequestMapping;")
        file_pointer.write("\n")
        file_pointer.write("import org.springframework.web.bind.annotation.RestController;")
        file_pointer.write("\n")
        if table_info.have_date or table_info.have_date_time:
            file_pointer.write("import java.util.Date;")
            file_pointer.write("\n")
        file_pointer.write("import java.util.List;")
        file_pointer.write("\n")
        build_controller_comment()
        file_pointer.write("\n")
        file_pointer.write("@RestController")
        file_pointer.write("\n")
        file_pointer.write(f"@RequestMapping(\"/{lower_first_char(table_info.bean_name)}\")")
        file_pointer.write("\n")
        file_pointer.write(f"public class {table_info.bean_name}Controller extends ABaseController{{")
        file_pointer.write("\n")
        file_pointer.write("\n")

    @staticmethod
    def build_impls(file_pointer: TextIO, table_info: TableInfo) -> None:
        def build_impls_helper(comment: str, content: str, retraction: str = "", inner_code: str = "", request_mapping: str=" ") -> None:
            file_pointer.write("\n")
            CommentBuilder.build_filed_comment(file_pointer, comment, retraction)
            file_pointer.write("\n")
            file_pointer.write(f"{retraction}@RequestMapping(\"{request_mapping}\")")
            file_pointer.write("\n")
            file_pointer.write(retraction + "public " + content)
            file_pointer.write(f"{{\n{retraction}{inner_code}\n{retraction}}}")
            file_pointer.write("\n")

        file_pointer.write("\n")
        file_pointer.write("\t@Resource")
        file_pointer.write("\n")
        file_pointer.write(
            f"\tprivate {table_info.bean_name}Service {lower_first_char(table_info.bean_name)}Service;"
        )

        service_name = lower_first_char(table_info.bean_name) + "Service"

        build_impls_helper(
            "根据条件分页查询",
            f"ResponseVO findListByParam({table_info.bean_param_name} query)",
            "\t",
            f"\treturn getSuccessResponseVO({service_name}.findListByPage(query));",
            "loadDataList"
        )

        add_inner = f"\t{service_name}.add(bean);"
        add_inner += "\n"
        add_inner += "\t\treturn getSuccessResponseVO(null);"

        build_impls_helper(
            "新增",
            f"ResponseVO add({table_info.bean_name} bean)",
            "\t",
            add_inner,
            "add"
        )

        add_batch_inner = f"\t{service_name}.addBatch(listBean);"
        add_batch_inner += "\n"
        add_batch_inner += f"\t\treturn getSuccessResponseVO(null);"
        build_impls_helper(
            "批量新增",
            f"ResponseVO addBatch(List<{table_info.bean_name}> listBean)",
            "\t",
            add_batch_inner,
            "addBatch"
        )

        add_batch_or_update_inner = f"\t{service_name}.addOrUpdateBatch(listBean);"
        add_batch_or_update_inner += "\n"
        add_batch_or_update_inner += f"\t\treturn getSuccessResponseVO(null);"

        build_impls_helper(
            "批量新增/修改",
            f"ResponseVO addOrUpdateBatch(List<{table_info.bean_name}> listBean)",
            "\t",
            add_batch_or_update_inner,
            "addOrUpdateBatch"
        )

        for i in table_info.field_map.values():
            props = uppercase_first_char(i.property_name)
            build_impls_helper(
                f"根据{i.property_name}查询",
                f"ResponseVO get{table_info.bean_name}By{props}({i.java_type} {i.property_name})",
                "\t",
                f"\treturn getSuccessResponseVO({service_name}.get{table_info.bean_name}By{props}({i.property_name}));",
                f"get{table_info.bean_name}By{props}"
            )

            build_impls_helper(
                f"根据{i.property_name}修改",
                f"ResponseVO update{table_info.bean_name}By{props}({table_info.bean_name} bean, {i.java_type} {i.property_name})",
                "\t",
                f"\t{service_name}.update{table_info.bean_name}By{props}(bean, {i.property_name});\n\t\treturn getSuccessResponseVO(null);",
                f"update{table_info.bean_name}By{props}"
            )

            build_impls_helper(
                f"根据{i.property_name}删除",
                f"ResponseVO delete{table_info.bean_name}By{props}({table_info.bean_name} bean, {i.java_type} {i.property_name})",
                "\t",
                f"\t{service_name}.delete{table_info.bean_name}By{props}(bean, {i.property_name});\n\t\treturn getSuccessResponseVO(null);",
                f"delete{table_info.bean_name}By{props}"
            )
